package com.cynteka.cyfoman.ui.collection;

import com.cynteka.cyfoman.core.ComplexPropertyResolver;
import com.cynteka.cyfoman.core.IPropertyResolver;
import com.cynteka.cyfoman.core.collection.CollectionRegistry;
import com.cynteka.cyfoman.core.collection.ICollection;
import com.cynteka.cyfoman.core.collection.ILink;
import com.cynteka.cyfoman.ui.Reloadable;

import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import java.util.*;

/**
 * User: Sergey
 * Date: 01.08.11
 * Time: 18:46
 */
public class CollectionTreeModel extends DefaultTreeModel implements TreeModel, Reloadable {

    private IPropertyResolver propertyResolver = new ComplexPropertyResolver();

    private CollectionRegistry collectionRegistry;
    private String rootCollection;
    private List<String> links;
    private Pair root;


    public CollectionTreeModel() {
        super(null);
    }

    public class Pair implements TreeNode {
        public final ICollection collection;
        public final Object value;
        private List<Pair> children;
        private Pair parent;

        public Pair(ICollection collection, Object value, Pair parent) {
            this.collection = collection;
            this.value = value;
            this.parent = parent;
        }

        @Override
        public int getChildCount() {
            initChildren();
            return children.size();
        }

        @Override
        public Pair getParent() {
            return parent;
        }

        @Override
        public int getIndex(TreeNode node) {
            return children.indexOf(node);
        }

        @Override
        public boolean getAllowsChildren() {
            // TODO think if it's necessary
            return true;
        }

        @Override
        public boolean isLeaf() {
            initChildren();
            return children.size() == 0;
        }

        @Override
        public Pair getChildAt(int idx) {
            initChildren();
            return children.get(idx);
        }

        @Override
        public Enumeration children() {
            final Iterator<Pair> iter = children.iterator();
            return new Enumeration<Pair>() {

                @Override
                public boolean hasMoreElements() {
                    return iter.hasNext();
                }

                @Override
                public Pair nextElement() {
                    return iter.next();
                }
            };
        }

        private void initChildren() {
            if (children == null) {
                children = new ArrayList();
                if (value == null) { // ROOT
                    Collection items = collection.getItems(null);
                    for (Object item : items) {
                        children.add(new Pair(collection, item, this));
                    }
                } else {
                    for (String linkId : links) {
                        ILink link = collectionRegistry.getLink(linkId);
                        if (link != null) {
                            if (link.getCollectionSourceId().equals(collection.getId())) {
                                Collection items = link.getDestinationItems(value);
                                ICollection destCollection = collectionRegistry.getCollection(link.getCollectionDestinationId());
                                for (Object item : items) {
                                    children.add(new Pair(destCollection, item, this));
                                }
                            }
                        }
                    }
                }
            }
        }

        @Override
        public String toString() {
            return "" + value;
        }

        public int getIndexOf(Object o) {
            // TODO implement it
            return 0;  //To change body of created methods use File | Settings | File Templates.
        }

        public void reload() {
            children = null;
            initChildren();
        }
    }

    protected class Root extends Pair {

        public Root() {
            super(null, null, null);
        }
    }


    public CollectionRegistry getCollectionRegistry() {
        return collectionRegistry;
    }

    public void setCollectionRegistry(CollectionRegistry collectionRegistry) {
        this.collectionRegistry = collectionRegistry;
    }

    public String getRootCollection() {
        return rootCollection;
    }

    public void setRootCollection(String rootCollection) {
        this.rootCollection = rootCollection;
    }

    public List<String> getLinks() {
        return links;
    }

    public void setLinks(List<String> links) {
        this.links = links;
    }

    @Override
    public Object getRoot() {
        initRoot();
        return super.getRoot();
    }

    private void initRoot() {
        if (root == null) {
            ICollection collection = collectionRegistry.getCollection(rootCollection);
            root = new Pair(collection, null, null);
            setRoot(root);
        }
    }

    /*
    @Override
    public Object getChild(Object parent, int index) {
        Pair pair = (Pair) parent;
        return pair.getChildAt(index);
    }
    //*/

    /*
    @Override
    public int getChildCount(Object parent) {
        Pair pair = (Pair) parent;
        return pair.getChildCount();
    }
    //*/

    /*
    @Override
    public boolean isLeaf(Object node) {
        Pair pair = (Pair)node;
        return pair.getChildCount() == 0;
    }
    //*/

    /*
    @Override
    public void valueForPathChanged(TreePath path, Object newValue) {
        //To change body of implemented methods use File | Settings | File Templates.
    }
    //*/

    /*
    @Override
    public int getIndexOfChild(Object parent, Object child) {
        Pair pair = (Pair)parent;
        return pair.getIndexOf(parent);
    }
    //*/

    /*
    @Override
    public void addTreeModelListener(TreeModelListener l) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void removeTreeModelListener(TreeModelListener l) {
        //To change body of implemented methods use File | Settings | File Templates.
    }
    //*/

    public IPropertyResolver getPropertyResolver() {
        return propertyResolver;
    }

    public void setPropertyResolver(IPropertyResolver propertyResolver) {
        this.propertyResolver = propertyResolver;
    }

    @Override
    public void reload(TreeNode node) {
        Pair pair = (Pair) node;
        pair.reload();
        super.reload(node);
    }
}
